home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ASME's Mechanical Engine…ing Toolkit 1997 December
/
ASME's Mechanical Engineering Toolkit 1997 December.iso
/
ai
/
prlg195b.lzh
/
GAMES.LZH
/
TTT.PRO
< prev
Wrap
Text File
|
1986-05-13
|
6KB
|
238 lines
/************************************************************************
*
* programer: Gregory L. Humphreys
*
* address: 43 Longwood Drive
* Hampton, VA 23669
*
* phone: (804) 851-4550 home
* (804) 865-4534 work
*
* date: 05-13-86
*
* program: Tic-Tac-Toe (TTT.PRO)
*
* description: This Prolog program plays a semi-intelligent game
* of Tic-Tac-Toe. It lets the user go first, and it
* will try to win, block a user win, else it tries
* to pick a good move based on preset values for the
* squares. To play the game, simply load the source
* via consult(ttt) and type go. You will be prompted
* for a move as X, etc. It will take the computer
* about 4 sec. to make a move so be patient. It is
* possible to trap the computer and win! Good Luck!
*
************************************************************************/
/* initialize the Board, the possible Moves, and the current move Count */
/* assert them as "gamestat" and invoke rule to prompt for user input */
go :-
Board = [[],[]],
Moves = [1,2,3,4,5,6,7,8,9],
Count is 0,
asserta (gamestat (Board, Moves, Count)),
getxmove.
/* retrieve current "gamestat", display current board, read the X move */
/* incr. Count, check if X wins, check for a "cat" game, then get O move */
getxmove :-
gamestat ([Xmoves, Omoves], Moves1, Count1),
printboard ([Xmoves,Omoves]),
readxmove (Moves1, Moves2, Newxmove),
Count2 is Count1 + 1,
!, xwins ([Newxmove|Xmoves], [[Newxmove|Xmoves], Omoves]),
catgame (Count2, [[Newxmove|Xmoves], Omoves]),
getomove ([[Newxmove|Xmoves], Omoves], Moves2, Count2),
!, getxmove.
getxmove. /* getxmove will always return true */
/* prompt for and read in an X move; validate it by translating its ASCII */
/* value to the internal magic square value and check if it is a member of */
/* the current set of moves, and if so then remove it from the move list */
readxmove (Moves1, Moves2, Newxmove) :-
repeat,
print (' Enter your move > '),
get0 (Newx), nl,
trans (Newxmove, Newx),
member (Newxmove, Moves1),
remove (Newxmove, Moves1, [], Moves2).
/* get a computer O move by returning a move that has the highest value */
/* incr. count, remove it from the move list, retract the old gamestat */
/* assert the new gamestat, display the O move */
getomove ([Xmoves,Omoves], Moves1, Count1) :-
getomove1 ([Xmoves,Omoves], Moves1, [], Count1, Value, Newomove),
Count2 is Count1 + 1,
remove (Newomove, Moves1, [], Moves2),
retract (gamestat (_,_,_)),
asserta (gamestat ([Xmoves,[Newomove|Omoves]], Moves2, Count2)),
trans (Newomove, Newo),
nl, print (' My move is > '),
put (Newo), nl, nl.
/* first check to see if O can win, else get an O move (recursively) */
/* via evaluating the board with each possible move (an X win is high */
/* value), and returning the highest valued move */
getomove1 ([Xmoves,Omoves], [First|Rest], Ext, Count1, Value1, Oout1) :-
owins ([First|Omoves], [Xmoves,[First|Omoves]]),
getomove1 ([Xmoves,Omoves], Rest, [First|Ext], Count1, Value2, Oout2),
evaluate (First, Xmoves, Value3),
maxvalue (Value3, Value2, Value1, First, Oout2, Oout1).
getomove1 (_, [], _, _, -100, []). /* the base case which is no good */
/* removes an element from a list */
remove (X, [], Ans, Ans).
remove (X, [X|Rest], Front, Ans) :-
remove (X, Rest, Front, Ans).
remove (X, [Y|Rest], Front, Ans) :-
remove (X, Rest, [Y|Front], Ans).
/* checks for a win for X, if so then it displays a message, etc. */
xwins (Xmoves, Board) :-
checkwin (Xmoves),
nl, printboard (Board),
nl, print (' you win '), nl,
retract (gamestat (_,_,_)),
!, fail.
xwins (_,_).
/* checks for a win for O, if so then it displays a message, etc. */
owins (Omoves, Board) :-
checkwin (Omoves),
nl, printboard (Board),
nl, print (' I win ! '), nl,
retract (gamestat (_,_,_)),
!, fail.
owins (_,_).
/* checks for a draw, if so then it displays a message, etc. */
catgame (9, Board) :-
nl, printboard (Board),
nl, print (' cat game '), nl,
retract (gamestat (_,_,_)),
!, fail.
catgame (_,_).
/* the maximum value is returned in the third param and a corresponding */
/* value is also propagated out */
maxvalue (Value1, Value2, Value1, Xout1, _, Xout1) :-
Value1 > Value2.
maxvalue (_, Value2, Value2, _, Xout2, Xout2).
/* evaluates the given board returning a value */
evaluate (First, Xmoves, 50) :-
checkwin ([First|Xmoves]). /* this has the best value */
evaluate (1, _, 1). /* value of a side is 1 */
evaluate (2, _, 2). /* value of a corner is 2 */
evaluate (3, _, 1).
evaluate (4, _, 2).
evaluate (5, _, 3). /* value of the center is 3 */
evaluate (6, _, 2).
evaluate (7, _, 1).
evaluate (8, _, 2).
evaluate (9, _, 1).
evaluate (_, _, 0).
/* checks for a win */
checkwin ([A|[B|C]]) :-
find15 (A, B, C).
/* looks for a winning combination via magic square value addition */
find15 (A, B, [C|D]) :-
(15 is A + B + C;
find15 (A, B, D);
find15 (A, C, D);
find15 (B, C, D)).
/* displays the given board */
printboard ([Xmoves,Omoves]) :-
nl,
markrow (8, 3, 4, [Xmoves,Omoves]),
nl,
print (' ---+---+---'),
nl,
markrow (1, 5, 9, [Xmoves,Omoves]),
nl,
print (' ---+---+---'),
nl,
markrow (6, 7, 2, [Xmoves,Omoves]),
nl, nl.
/* draws one of the three rows of the board */
markrow (A, B, C, [Xmoves,Omoves]) :-
print (' '),
mark (A, [Xmoves,Omoves]),
print (' | '),
mark (B, [Xmoves,Omoves]),
print (' | '),
mark (C, [Xmoves,Omoves]).
/* marks with an X or an O or a number for an open square */
mark (Z, [Xmoves,Omoves]) :-
(member (Z, Xmoves), print ('X'));
(member (Z, Omoves), print ('O'));
(trans (Z, Y), put (Y)).
/* translates between magic square and ASCII values for each square */
trans (8, 49).
trans (3, 50).
trans (4, 51).
trans (1, 52).
trans (5, 53).
trans (9, 54).
trans (6, 55).
trans (7, 56).
trans (2, 57).
/* finds out if an element is a member of a list */
member (Y, [Y|_]).
member (B, [_|C]) :-
member (B, C).